package cn.com.goldhs.architecture.inter.impl;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.helpers.collection.IterableWrapper;

import cn.com.goldhs.architecture.RelationShipTypes;
import cn.com.goldhs.architecture.inter.Base;
import cn.com.goldhs.architecture.inter.Department;
import cn.com.goldhs.architecture.inter.Leader;
import cn.com.goldhs.architecture.util.ContainerWrapperWithName;

public class BaseImpl extends ContainerWrapperWithName<Node>
		implements Base {

	public BaseImpl(Node node) {
		super(node);
	}

	public BaseImpl(Node node, String name) {
		super(node, name);
	}

	@Override
	public long getId() {
		return this.getUnderlyingContainer().getId();
	}

	@Override
	public void addSubDept(Department dept) {
		this.getUnderlyingContainer().createRelationshipTo(
				((DepartmentImpl) dept).getUnderlyingContainer(),
				RelationShipTypes.SubDept);

	}

	@Override
	public void remove() {
		for (Relationship rel : this.getUnderlyingContainer()
				.getRelationships()) {
				rel.delete();
		}
		this.getUnderlyingContainer().delete();
	}

	@Override
	public void moveToLeader(Leader leader) {
		Iterable<Relationship> rels = this.getUnderlyingContainer()
				.getRelationships(Direction.INCOMING);

		for (Relationship rel : rels) {
			rel.delete();
		}

		if (this instanceof Department)
			leader.addSubDept((Department) this);
		else
			leader.addSubLeader((Leader) this);
	}

	@Override
	public Iterable<Department> listSubDepts() {
		Traverser traverser = this.getUnderlyingContainer().traverse(
				Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE,
				ReturnableEvaluator.ALL_BUT_START_NODE,
				RelationShipTypes.SubDept, Direction.OUTGOING);

		return new IterableWrapper<Department, Node>(traverser) {
			@Override
			protected Department underlyingObjectToObject(Node node) {
				return new DepartmentImpl(node);
			}
		};
	}

	@Override
	public Iterable<Base> listSubAll() {
		Traverser traverser = this.getUnderlyingContainer().traverse(
				Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE,
				ReturnableEvaluator.ALL_BUT_START_NODE,
				RelationShipTypes.SubDept, Direction.OUTGOING,
				RelationShipTypes.SubLeader, Direction.OUTGOING);

		return new IterableWrapper<Base, Node>(traverser) {
			@Override
			protected Base underlyingObjectToObject(Node node) {
				
				if (node.hasRelationship(RelationShipTypes.SubLeader,
						Direction.INCOMING))
					return new LeaderImpl(node);
				else if (node.hasRelationship(RelationShipTypes.SubDept,
						Direction.INCOMING))
					return new DepartmentImpl(node);
				else {
					return null; // never do it
				}

			}
		};
	}
	
	@Override
	public Base getParent() {
		return null;
	}

}
